from typing_extensions import Annotated
from fastapi import HTTPException, Request, Depends, WebSocket, Query
from fastapi.security import SecurityScopes
from package.fastapi.security import jwt
from package.fastapi.auth import auth
from package.fastapi import cache


async def get_current_user_by_ws(
        authorization_code: Annotated[str , Query()] = None,
        apikey: Annotated[str , Query()] = None,
        token: Annotated[str , Query()] = None,
        ):

    if authorization_code:  # 用户级别授权
        current_user = cache.authorization_cache.get(authorization_code)
        if not current_user:
            raise HTTPException(status_code=401, detail='无效Authorization Code')
        return current_user

    if apikey:  # 系统级别授权
        current_user = cache.apikey_cache.get(apikey)
        if not current_user:
            raise HTTPException(status_code=401, detail='无效APIKEY')
        return current_user

    try:
        token_data = jwt.decode(token)
    except Exception as e:
        raise HTTPException(status_code=401, detail='无效Token')

    current_user = cache.token_cache.get(token_data['id'])
    if not current_user:
        raise HTTPException(status_code=401, detail='无效Token')
    return current_user


async def get_current_user(request: Request = None, token=Depends(auth.oauth2_scheme)):
    """获取当前登陆用户
    1. 用户授权
    2. 系统授权
    3. 用户帐号密码 token
    """
    if authorization_code := request.headers.get('X-Authorization-Code'):  # 用户级别授权
        current_user = cache.authorization_cache.get(authorization_code)
        if not current_user:
            raise HTTPException(status_code=401, detail='无效Authorization Code')

        request.state.auth = {'type': 'authorization_code', 'value': authorization_code}
        request.state.user = current_user
        return current_user

    if apikey := request.headers.get('X-API-KEY'):  # 系统级别授权
        current_user = cache.apikey_cache.get(apikey)
        if not current_user:
            raise HTTPException(status_code=401, detail='无效APIKEY')

        request.state.auth = {'type': 'api_key', 'value': apikey}
        request.state.user = current_user
        return current_user

    try:
        token_data = jwt.decode(token)
    except Exception as e:
        raise HTTPException(status_code=401, detail='无效Token')

    current_user = cache.token_cache.get(token_data['id'])
    if not current_user:
        raise HTTPException(status_code=401, detail='无效Token')

    request.state.user = current_user
    request.state.auth = {'type': 'authorization', 'value': token}
    return current_user


async def security(user=Depends(get_current_user), scopes: SecurityScopes = None,
                   request: Request = None):
    if not scopes.scopes:  # 登陆即可访问函数
        return user
    if 'Administrator' in [role['name'] for role in user['roles']]:  # 管理员角色
        return user
    for role in user['roles']:  # 多个角色取并集 其中一个角色可访问即可访问该功能
        mod_scopes = {scope['router']:  scope['mod']
                      for module in role.get('permit', []) if module.get('visible')
                      for sub_module in module.get('sub_module', []) if sub_module.get('visible')  # 子模块隐藏 禁止访问
                      for scope in sub_module.get('scopes', []) if scope.get('visible')}
        for scope in scopes.scopes:
            router, mod = scope.split(':')
            if mod_scopes.get(router) in (mod, 'write'):  # 给定的read 目标函数也是read， 或给定的write
                return user

    raise HTTPException(status_code=403, detail='用户权限不足')


async def security_ws(user=Depends(get_current_user_by_ws), scopes: SecurityScopes = None):
    if not scopes.scopes:  # 登陆即可访问函数
        return user
    if 'Administrator' in [role['name'] for role in user['roles']]:  # 管理员角色
        return user
    for role in user['roles']:  # 多个角色取并集 其中一个角色可访问即可访问该功能
        mod_scopes = {scope['router']:  scope['mod']
                      for module in role.get('permit', []) if module.get('visible')
                      for sub_module in module.get('sub_module', []) if sub_module.get('visible')  # 子模块隐藏 禁止访问
                      for scope in sub_module.get('scopes', []) if scope.get('visible')}
        for scope in scopes.scopes:
            router, mod = scope.split(':')
            if mod_scopes.get(router) in (mod, 'write'):  # 给定的read 目标函数也是read， 或给定的write
                return user

    raise HTTPException(status_code=403, detail='用户权限不足')
